package com.darwin.darwinBitmapEngine.core
{
	import com.darwin.darwinBitmapEngine.utils.G_ID;
	
	import flash.display.BitmapData;
	import flash.events.EventDispatcher;
	import flash.filters.BitmapFilter;
	import flash.filters.BlurFilter;
	import flash.filters.GlowFilter;
	import flash.geom.Matrix;
	import flash.geom.Point;
	import flash.geom.Rectangle;
	import flash.utils.getTimer;

	/**
	 * 显示节点 
	 * @author lipi
	 */
	public class Node extends EventDispatcher implements INode
	{
		public function Node(bitmapData:BitmapData = null)
		{
			_bitmapData = bitmapData;
			_g_ID = G_ID.id;
		}
		
		private var _g_ID:uint;
		public function get g_ID():uint
		{
			return _g_ID;
		}
		
		
		//源位图数据
		private var _bitmapData:BitmapData;
		//滤镜或缩放,旋转等矩阵变换产生的位图数据
		private var _transBitmapData:BitmapData;
		// 
		/**
		 * 取得要显示的位图
		 * @return 
		 */
		public function get bitmapData():BitmapData
		{
			if(_transBitmapData != null)
			{
				return _transBitmapData;
			}
			return _bitmapData;
		}
		
		/**
		 * 设置位图 
		 * @param bitmapData 
		 */
		public function set bitmapData(bitmapData:BitmapData):void
		{
			_bitmapData = bitmapData;
			setTransBitmapData();
			markChange();
		}
		
		
		private var _filter:BitmapFilter;
		/**
		 * 位图滤镜
		 */
		public function get filter():BitmapFilter
		{
			return _filter;
		}

		public function set filter(value:BitmapFilter):void
		{
			if(value != _filter)
			{
				_filter = value;
				setTransBitmapData();
				markChange();
			}
		}
		
		/**
		 * 设置滤镜/矩阵变换位图
		 */
		private function setTransBitmapData():void
		{
			if(_transBitmapData!= null)
			{
				_transBitmapData.dispose();
				_transBitmapData = null;
			}
			var $m:Matrix;
			if(_scaleX != 1.0 || _scaleY != 1.0)
			{
				$m = new Matrix();
				$m.scale(_scaleX,_scaleY);
			}
			_transBitmapData = createTransBitmapData(_bitmapData,_filter,$m);
		}
		
		
		/**
		 * 生成滤镜/矩阵变换后的位图(注：一次滤镜的执行时间为18毫秒)
		 * @param sourceBitmapData 源位图图像
		 * @param bitmapFilter 使用的滤镜
		 * @param matrix 变换矩阵
		 * @return 生成滤镜后的位图 
		 */
		protected function createTransBitmapData(sourceBitmapData:BitmapData,bitmapFilter:BitmapFilter,matrix:Matrix):BitmapData
		{
			var $returnBitmapData:BitmapData;
			if(sourceBitmapData != null && (matrix || bitmapFilter))
			{
				$returnBitmapData = new BitmapData(sourceBitmapData.width,sourceBitmapData.height,true,0);
				if(matrix)
				{
					$returnBitmapData.draw(sourceBitmapData,matrix,null,null,null,true);
				}
				if(bitmapFilter)
				{
					$returnBitmapData.applyFilter(sourceBitmapData,$returnBitmapData.rect,new Point(),bitmapFilter);
				}
			}
			return $returnBitmapData;
		}
		
		
		private var _rect:Rectangle;
		/**
		 * 设置显示区域，如果不设置则返回位图区域
		 * @param value 
		 */
		public function set rect(value:Rectangle):void
		{
			_rect = value;
			markChange();
		}
		/**
		 * 取得位图区域，默认为位图区域
		 * @return 返回当前区域 
		 */
		public function get rect():Rectangle
		{
			if(_bitmapData == null) return null;
			return _rect || _bitmapData.rect;
		}
		
		
		private var _parent:IContainer;
		/**
		 * 所在的父级
		 * @param value
		 */
		public function set parentContainer(value:IContainer):void
		{
			_parent = value;
		}
		
		public function get parentContainer():IContainer
		{
			return _parent;
		}
		
		//状态改变标记
		protected function markChange():void
		{
			if(this.parentContainer && this.parentContainer is INode)
			{
				this.parentContainer.markChange(this.parentContainer as INode);
			}else if(this.parentContainer){
				this.parentContainer.markChange(this);
			}
		}
		
		
		private var _redrawRect:Rectangle;

		/**
		 * 重绘区域
		 * @return 返回重绘的区域 
		 */
		public function get redrawRect():Rectangle
		{
			return _redrawRect;
		}

		public function set redrawRect(value:Rectangle):void
		{
			_redrawRect = value;
		}
		
		
		
		public function get offsetPoint():Point
		{
			return null;
		}
		
		
		protected var _x:Number = 0; 

		public function get x():Number
		{
			return _x;
		}

		public function set x(value:Number):void
		{
			if(_x != value)
			{
				_x = value;
				markChange();
			}
		}
		
		
		protected var _y:Number = 0;

		public function get y():Number
		{
			return _y;
		}

		public function set y(value:Number):void
		{
			if(_y != value)
			{
				_y = value;
				markChange();
			}
		}
		
		
		protected var _scaleX:Number = 1.0;
		
		/**
		 *	X轴方向缩放 
		 * <br/> <b>注意：</b>设置此值为1.0以外的值时将导致播放方式更改为每帧重绘而非替换bitmapData，可能会导致性能下降，请谨慎使用。
		 */
		public function get scaleX():Number
		{
			return _scaleX;
		}
		
		/**
		 * @private
		 */
		public function set scaleX(value:Number):void
		{
			if(_scaleX != value)
			{
				_scaleX = value;
				markChange();
			}
		}
		
		protected var _scaleY:Number = 1.0;
		
		/**
		 *	Y轴方向缩放 
		 * <br/> <b>注意：</b>设置此值为1.0以外的值时将导致播放方式更改为每帧重绘而非替换bitmapData，可能会导致性能下降，请谨慎使用。
		 */
		public function get scaleY():Number
		{
			return _scaleY;
		}
		
		/**
		 * @private
		 */
		public function set scaleY(value:Number):void
		{
			if(_scaleY != value)
			{
				_scaleY = value;
				markChange();
			}
		}

		protected var _width:Number = 0;

		public function get width():Number
		{
			return rect.width;
		}

/*		public function set width(value:Number):void
		{
			_width = value; 
		}*/
		
		
		protected var _height:Number = 0;

		public function get height():Number
		{
			return rect.height;
		}
		
		
		private var _visible:Boolean = true;
		
		/**
		 * 是否可见
		 */
		public function set visible(value:Boolean):void
		{
			if(_visible != value)
			{
				_visible = value;
				markChange();
			}
		}
		
		public function get visible():Boolean
		{
			return _visible;
		}
		
		
/*		public function set height(value:Number):void
		{
			_height = value; 
		}*/
		
		
		
		/**
		 * 执行渲染前处理。对于动画需要调整显示距形的位置 
		 */
		public function render():void
		{
		}
		
		
		private var _clickEnabled:Boolean = false;
		/**
		 * 是否允许单击
		 */
		public function set clickEnabled(value:Boolean):void
		{
			_clickEnabled = value;
		}
		public function get clickEnabled():Boolean
		{
			return _clickEnabled;
		}
		
		private var _mouseHoverEnabled:Boolean = false;
		/**
		 * 是否允许鼠标滑入滑出
		 */
		public function set mouseHoverEnabled(value:Boolean):void
		{
			_mouseHoverEnabled = value;
		}
		public function get mouseHoverEnabled():Boolean
		{
			return _mouseHoverEnabled;
		}
		
		/** 
		 * 检测是否碰撞 
		 * @param x 节点x坐标 
		 * @param y 节点y坐标 
		 * @param alphaThreshold 透明度检测阀值，透明度大于这个值的将直接当作不透明来处理
		 */
		public function hitTest(x:Number,y:Number,alphaThreshold:uint = 0x00):Boolean
		{
			if(this.rect == null) return false;
			if(this.bitmapData == null) return false;
			
			var $rect:Rectangle = this.rect.clone();
			$rect.x = 0;
			$rect.y = 0;
			
			if($rect.contains(x,y))
			{
				var $point:Point = new Point(this.rect.x+x,this.rect.y+y);
				var $color:uint = this.bitmapData.getPixel32($point.x,$point.y);
				
				var alpha:Number = $color >>> 24;
				if(alpha > alphaThreshold)
				{
					return true;
				}
			}
			return false;
		}
		
		public function localToGlobal(point:Point):Point
		{
			var newPoint:Point = new Point();
			if(parentContainer)
			{
				if(parentContainer is Canvas)
				{
					var canvasGlobalPoint:Point = canvas.localToGlobal(new Point);
					newPoint = new Point(x + point.x + canvas.contentX + canvasGlobalPoint.x,y + point.y + canvas.contentY + canvasGlobalPoint.y);
				}
				else if(parentContainer is ContainerNode)
				{
					var containerNode:ContainerNode = parentContainer as ContainerNode;
					var containerGlobalPoint:Point = containerNode.localToGlobal(new Point);
					newPoint = new Point(x + point.x + containerGlobalPoint.x,y + point.y + containerGlobalPoint.y);
				}
			}
			return newPoint; 
		}

		/**
		 *	获取负责绘制自己的画布 
		 * @return 
		 * 
		 */
		private function get canvas():Canvas
		{
			if(parentContainer && parentContainer is ContainerNode)
			{
				return (parentContainer as ContainerNode).parentContainer as Canvas;
			}
			return null;
		}
		
		private var _renderNotify:Boolean = false;
		

		public function exeRenderNotify():void
		{
			
		}
		
		
		/**
		 *	是否需要在渲染完成之后接收渲染完成通知
		 * @param value
		 * 
		 */
		public function set renderNotify(value:Boolean):void
		{
			_renderNotify = value;
		}
		
		public function get renderNotify():Boolean
		{
			return _renderNotify;
		}
		
	}
}